package com.smedi.ismedi.cronjob.api.infrastructure.cron;

import com.smedi.ismedi.cronjob.api.infrastructure.enumerate.CronParamEnum;
import com.smedi.ismedi.cronjob.api.infrastructure.enumerate.CronTypeEnum;

import java.time.LocalDateTime;

public class CronExpressionBuild {
    public static CronExpression builder(String expression) {
        CronExpression cronExpression = new CronExpression();
        try {
            // cron 格式 由 5或6个空格，6或7个值域
            String[] es = expression.split(" ");
            if (es.length > 7 && es.length < 6) {
                return null;
            }

            cronExpression.setSeconds(toCron(es[0]));
            cronExpression.setMinutes(toCron(es[1]));
            cronExpression.setHour(toCron(es[2]));
            cronExpression.setDay(toCron(es[3]));
            cronExpression.setMonth(toCron(es[4]));
            cronExpression.setWeek(toCron(es[5]));

            // 年 可以省略
            if (es.length == 7) {
                cronExpression.setYear(toCron(es[6]));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return cronExpression;
    }

    public static CronExpression builder(LocalDateTime localDateTime) {
        CronExpression cronExpression = new CronExpression();

        cronExpression.setSeconds(CronType.builder(localDateTime.getSecond()));

        cronExpression.setMinutes(CronType.builder(localDateTime.getMinute()));

        cronExpression.setHour(CronType.builder(localDateTime.getHour()));

        cronExpression.setDay(CronType.builder(localDateTime.getDayOfMonth()));

        cronExpression.setMonth(CronType.builder(localDateTime.getMonthValue()));

        cronExpression.setWeek(CronType.builder(CronTypeEnum.NONE, null));

        cronExpression.setYear(CronType.builder(localDateTime.getYear()));

        return cronExpression;
    }

    public static CronExpression builder(LocalDateTime localDateTime, CronParamEnum cronParamEnum) {
        CronExpression cronExpression = builder(localDateTime);

        if (cronParamEnum == null) {
            return cronExpression;
        }

        CronType everyTime = CronType.builder(CronTypeEnum.EVERY_TIME, null);

        if (CronParamEnum.EVERY_SECONDS.equals(cronParamEnum)) {
            return builder("* * * * * ? *");
        }

        if (CronParamEnum.EVERY_MINUTES.equals(cronParamEnum)) {
            cronExpression.setMinutes(everyTime);
            cronExpression.setHour(everyTime);
            cronExpression.setDay(everyTime);
            cronExpression.setMonth(everyTime);
            cronExpression.setWeek(CronType.builder(CronTypeEnum.NONE, null));
            cronExpression.setYear(everyTime);
        }

        if (CronParamEnum.EVERY_HOURS.equals(cronParamEnum)) {
            cronExpression.setHour(everyTime);
            cronExpression.setDay(everyTime);
            cronExpression.setMonth(everyTime);
            cronExpression.setWeek(CronType.builder(CronTypeEnum.NONE, null));
            cronExpression.setYear(everyTime);
        }

        if (CronParamEnum.EVERY_DAY.equals(cronParamEnum)) {
            cronExpression.setDay(everyTime);
            cronExpression.setMonth(everyTime);
            cronExpression.setWeek(CronType.builder(CronTypeEnum.NONE, null));
            cronExpression.setYear(everyTime);
        }

        if (CronParamEnum.EVERY_MONTH.equals(cronParamEnum)) {
            cronExpression.setMonth(everyTime);
            cronExpression.setWeek(CronType.builder(CronTypeEnum.NONE, null));
            cronExpression.setYear(everyTime);
        }

        if (CronParamEnum.EVERY_WEEK.equals(cronParamEnum)) {
            cronExpression.setDay(CronType.builder(CronTypeEnum.NONE, null));
            cronExpression.setWeek(everyTime);
            cronExpression.setYear(everyTime);
        }
        return cronExpression;
    }

    public static CronType toCron(String str) {
        switch (str) {
            case "?":
                return CronType.builder(CronTypeEnum.NONE, null);
            case "*":
                return CronType.builder(CronTypeEnum.EVERY_TIME, null);
            case "L":
                return CronType.builder(CronTypeEnum.LAST, null);
            default:
                if ("/".indexOf(str) >= 0) {
                    String s1 = str.substring(0, str.indexOf("/"));
                    String s2 = str.substring(str.indexOf("/"));
                    return CronType.builder(CronTypeEnum.INTERVAL, new String[]{s1, s2});
                }
                if ("-".indexOf(str) >= 0) {
                    String s1 = str.substring(0, str.indexOf("-"));
                    String s2 = str.substring(str.indexOf("-"));
                    return CronType.builder(CronTypeEnum.SECTION, new String[]{s1, s2});
                }
                String[] s = str.split(",");
                return CronType.builder(CronTypeEnum.AGGREGATE, s);
        }
    }
}
